home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / sys / getkey.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  5KB  |  221 lines

  1.  
  2. /*
  3.  * @(#)getkey.c 1.1 86/09/27
  4.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  5.  */
  6.  
  7. /*
  8.  * getkey.c
  9.  *
  10.  * Keyboard decoding routine for Sun Monitor
  11.  *
  12.  * This module decodes keyboard up/down codes put in a buffer by
  13.  * "keypress", turns them into ASCII, and passes them on to the rest
  14.  * of the world, one at a time.
  15.  *
  16.  * There are currently two options.  You can request up/down codes,
  17.  * in which case we just leave the driving to you; or you can
  18.  * request ASCII codes, in which case we deal with remembering
  19.  * case shifts, Repeat keys, Ascii translations, etc, and you just
  20.  * see the kind of bytes that might come in from a terminal.
  21.  *
  22.  * We default to providing ASCII.
  23.  */
  24.  
  25.  
  26. /*
  27.  * #define KEYBARF invokes some consistency checks on the data received,
  28.  * doing printf's if anything is wrong.
  29.  */
  30.  
  31. #include "../h/keyboard.h"
  32. #include "../h/asyncbuf.h"
  33. #include "../h/globram.h"
  34.  
  35. extern struct keyboard    *keytables[];
  36. extern char *keystringtab[];
  37.  
  38. /* 
  39.  * Getkey Initialization
  40.  *
  41.  */
  42. initgetkey()
  43. {
  44. #ifdef KEYBARF
  45.     unsigned char *keyptr = &gp->keyswitch[0];
  46.  
  47.     while (keyptr < &gp->keyswitch[128]) 
  48.         *keyptr++ = RELEASED;
  49. #endif KEYBARF
  50.  
  51.     gp->g_shiftmask = 0;
  52.     gp->g_translation = TR_ASCII;
  53.     gp->g_keyrtick = 1000/13;    /* 13 cps repeat rate */
  54.     gp->g_keyrinit = 500;        /* Wait .5 sec before repeating */
  55.     gp->g_keyrkey = IDLEKEY;    /* Nothing happening now */
  56. }
  57.  
  58.  
  59. /*
  60.  * This routine fixes up our tables after an Abort, so we won't
  61.  * think we detected spurious ups or downs.  The refresh routine
  62.  * has seen these two keys go down but has not told us about them.
  63.  * We, however, will see them go up, and this lets us know that
  64.  * their upgoings are OK.
  65.  *
  66.  * This routine is called from the refresh routine or the start
  67.  * of the monitor code for an Abort.  If it fails, Aborts won't work.
  68.  */
  69. abortfix()
  70. {
  71.  
  72. #ifdef KEYBARF
  73.     gp->keyswitch[ABORTKEY1] = PRESSED;
  74.     gp->keyswitch[ABORTKEY2] = PRESSED;
  75. #endif KEYBARF
  76.     /* Tell mainline that keyboard is idle, (even tho it isn't)
  77.        to avoid its thinking that an autorepeat should occur */
  78.     bput (gp->g_keybuf, IDLEKEY);
  79. }
  80.  
  81. /*
  82.  * getkey()
  83.  *
  84.  * Returns a key code (if up/down codes being returned),
  85.  *     a byte of ASCII (if that's requested)
  86.  *     NOKEY (if no key has been hit).
  87.  */
  88. int getkey ()
  89. {
  90.     register unsigned char keycode, key, entry;
  91.     unsigned char notrepeating;
  92.  
  93.     while (1) {
  94.     /* Loop til a value-returning key is pressed or buffer is empty */
  95.  
  96.     if (!bgetp(gp->g_keybuf)) {
  97.         if (gp->g_keyrkey != IDLEKEY) {
  98.             if (gp->g_nmiclock >= gp->g_keyrtime) {
  99.                 gp->g_keyrtime = gp->g_keyrtick + gp->g_nmiclock;
  100.                 keycode = gp->g_keyrkey;
  101.                 notrepeating = 0;  /* We are repeating */
  102.                 goto interpretkeycode;
  103.             }
  104.         }
  105.         return (NOKEY); /* Either no autorepeat or no tick yet. */
  106.     }
  107.  
  108.     bget(gp->g_keybuf, keycode);
  109.     notrepeating = 1;    /* We are not repeating */
  110.  
  111. interpretkeycode:
  112.  
  113.     key = KEYOF(keycode);
  114.  
  115.     if (gp->g_translation == TR_NONE) 
  116.         return (keycode);
  117.     /* The only other value currently supported is TR_ASCII. */
  118.  
  119.     /* Translate key number and current shifts to an action byte */
  120.     if (gp->g_shiftmask & SHIFTMASK)
  121.         entry = keytables[0]->k_shifted->keymap[key];
  122.     else
  123.         entry = keytables[0]->k_normal ->keymap[key];
  124.  
  125.     if (notrepeating) {
  126.         register unsigned char enF0;
  127.  
  128.         enF0 = entry & 0xF0;
  129.         if ((STATEOF(keycode) == PRESSED) &&
  130. /* We might need to add the RESET/IDLE/ERROR entries here.  FIXME? */
  131.             (NOSCROLL  != entry) &&
  132.             (SHIFTKEYS != enF0) &&
  133.             (BUCKYBITS != enF0) ) {
  134.             gp->g_keyrkey = keycode;
  135.             gp->g_keyrtime = gp->g_nmiclock + gp->g_keyrinit;
  136.         } else {
  137.             if (key == KEYOF(gp->g_keyrkey))
  138.                 gp->g_keyrkey = IDLEKEY;
  139.         }
  140.     }
  141.  
  142.     /* If key is going up and is not a reset or shift key, ignore it. */
  143.     if (STATEOF(keycode) != PRESSED) {
  144.         if (keycode == RESETKEY)    /* Reset has key-up bit on */
  145.             entry = RESET;
  146.         else
  147.              if ((entry&0xF0) != SHIFTKEYS)
  148.             entry = NOP;
  149.     }
  150.  
  151.     switch (entry >> 4) {
  152.  
  153.     case 0:
  154.     case 1:
  155.     case 2:
  156.     case 3:
  157.     case 4:
  158.     case 5:
  159.     case 6:
  160.     case 7:
  161.         /* Map normal ascii depending on ctrl, capslock */
  162.         if (gp->g_shiftmask & CTRLMASK) entry &= 0x1F;
  163.         if ((gp->g_shiftmask & CAPSMASK) &&
  164.             (entry >= 'a' && entry <= 'z'))
  165.                 entry += 'A' - 'a';
  166.         return entry;
  167.  
  168.     case SHIFTKEYS >> 4:
  169.         gp->g_shiftmask ^= 1 << (entry & 0x0F);
  170.         break;
  171.  
  172.     case FUNNY >> 4:
  173.         switch (entry) {
  174.         case NOP:
  175.             break;
  176.  
  177.         case NOSCROLL:
  178.             if (gp->g_shiftmask & CTLSMASK)    goto sendcq;
  179.             else                goto sendcs;
  180.  
  181.         case CTRLS:
  182.         sendcs:
  183.             gp->g_shiftmask |= CTLSMASK;
  184.             return (('S'-0x40) /* | gp->g_buckybits */);
  185.  
  186.         case CTRLQ:
  187.         sendcq:
  188.             gp->g_shiftmask &= ~CTLSMASK;
  189.             return (('Q'-0x40) /* | gp->g_buckybits */);
  190.  
  191.         case IDLE:
  192.         case RESET:
  193.         gotreset:
  194.             gp->g_shiftmask &= keytables[0]->k_idleshifts;
  195.             gp->g_keyrkey = IDLEKEY;    /* Don't repeat */
  196.             break;
  197.  
  198.         case ERROR:
  199.             printf("Keyboard error detected\n");
  200.             goto gotreset;
  201.  
  202. /* Remember when adding new entries that, if they should NOT auto-repeat,
  203. they should be put into the IF statement just above this switch block.
  204. */
  205.         default:
  206.             goto badentry;
  207.         }
  208.         break;
  209.  
  210.     /*
  211.      * Remember when adding new entries that, if they should NOT
  212.      * auto-repeat, they should be put into the IF statement just above
  213.      * this switch block.
  214.      */
  215.     default:
  216.     badentry:
  217.         break;
  218.     }
  219.     }
  220. }
  221.